#include <cassert>
#include "PacMan.h"
#include "PacManGame.h"
#include "Ghost.h"

PacMan::PacMan( )
: animationPosition(0)
{
	type = OBJ_PACMAN;
	orientation = START;
}

PacMan::~PacMan( )
{
}

void PacMan::render( )
{


	glPushAttrib( GL_TEXTURE_BIT );
	glPushMatrix( );
		glTranslatef( X * Game::BLOCK_WIDTH, Y * Game::BLOCK_HEIGHT, 0 );
		
		switch( orientation )
		{
			case UP:
				glRotatef( 0.0f, 0, 0, 1 );
				break;
			case LEFT:
				glTranslatef( Game::BLOCK_WIDTH, 0,  0 );
				glRotatef( 90.0f, 0, 0, 1 );
				break;
			case DOWN:
				glTranslatef( Game::BLOCK_WIDTH, Game::BLOCK_HEIGHT,  0 );
				glRotatef( 180.0f, 0, 0, 1 );
				break;
			case RIGHT:
				glTranslatef( 0, Game::BLOCK_HEIGHT, 0 );
				glRotatef( 270.0f, 0, 0, 1 );
				break;
			default: break;
		}

		glMatrixMode( GL_TEXTURE );
		glPushMatrix( );
		glLoadIdentity( );
		glScalef( 1.0f / 2.0f, 1.0f, 1.0f );
		glTranslatef( animationPosition, 0, 0 );
		glMatrixMode( GL_MODELVIEW );

		glBindTexture( GL_TEXTURE_2D, Game::nPacManTexture );
		glCallList( Object::m_DisplayList );

		glMatrixMode( GL_TEXTURE );
		glPopMatrix( );
		glMatrixMode( GL_MODELVIEW );
	glPopMatrix( );
	glPopAttrib( );
}

void PacMan::update( )
{
	animationPosition = animationPosition == 1 ? 0 : 1;

	switch( orientation )
	{
		case UP:
			moveUp( );
			break;
		case LEFT:
			moveLeft( );
			break;
		case DOWN:
			moveDown( );
			break;
		case RIGHT:
			moveRight( );
			break;
		default: break;
	}

}


void PacMan::moveUp( )
{
	orientation = UP;
		
	if( !isCollision( X, Y + 1 ) )
		Y += 1;

	if( Y >= Game::GAME_BOARD_SIZE )
		Y = 0;
}

void PacMan::moveDown( )
{
	orientation = DOWN;

	if( !isCollision( X, Y - 1 ) )
		Y -= 1;

	if( Y < 0 )
		Y = Game::GAME_BOARD_SIZE - 1;
}

void PacMan::moveLeft( )
{	
	orientation = LEFT;
	
	if( !isCollision( X - 1, Y ) )
		X -= 1;

	if( X < 0 )
		X = Game::GAME_BOARD_SIZE - 1;
}

void PacMan::moveRight( )
{
	orientation = RIGHT;	

	if( !isCollision( X + 1, Y ) )
		X += 1;

	if( X >= Game::GAME_BOARD_SIZE)
		X = 0;
}



bool PacMan::isCollision( int x, int y )
{
	// wrap around...
	if( y < 0 ) y = Game::GAME_BOARD_SIZE + y;
	if( x < 0 ) x = Game::GAME_BOARD_SIZE + x;
	if( y >= Game::GAME_BOARD_SIZE ) y = y - Game::GAME_BOARD_SIZE;
	if( x >= Game::GAME_BOARD_SIZE ) x = x - Game::GAME_BOARD_SIZE;

	unsigned int index = y * Game::GAME_BOARD_SIZE + x;
	
	ObjectType collidingObjectType = Game::gameBoard[ index ]->type;


	if( collidingObjectType == OBJ_SMALL_DOT )
	{
		Game::soundSystem->playSound( FMOD_CHANNEL_FREE, Game::soundEffects[ Game::SFX_SMALL_DOT_EATEN ], false, 0 );

		delete Game::gameBoard[ index ];
		Game::gameBoard[ index ] = new Empty( );
		Game::gameBoard[ index ]->X = x;
		Game::gameBoard[ index ]->Y = y;
		Game::nScore += Game::SMALL_DOT_POINTS;
		Game::nDotCount--;
	}
	
	if( collidingObjectType == OBJ_BIG_DOT )
	{
		Game::soundSystem->playSound( FMOD_CHANNEL_FREE, Game::soundEffects[ Game::SFX_BIG_DOT_EATEN ], false, 0 );

		delete Game::gameBoard[ index ];
		Game::gameBoard[ index ] = new Empty( );
		Game::gameBoard[ index ]->X = x;
		Game::gameBoard[ index ]->Y = y;
		Game::nScore += Game::BIG_DOT_POINTS;
		Game::nDotCount--;
		Ghost::setAllGhostToFlee( );
		glutTimerFunc( 2500 * (1 + Game::NUMBER_OF_LEVELS - Game::nLevel), Game::setGhostSeekPacManMode, 0 );
	}

	if( collidingObjectType == OBJ_BLOCK )
		return true;
	else 
	{
		for( unsigned int g = 0; g < Game::nNumberOfGhosts; g++ )
		{
			Ghost *pGhost = static_cast<Ghost *>( Game::ghosts[ g ] );
			if( pGhost->X == x && pGhost->Y == y )
			{
				if( pGhost->getState( ) == Ghost::FLEEING_PACMAN )
				{					
					Game::soundSystem->playSound( FMOD_CHANNEL_FREE, Game::soundEffects[ Game::SFX_GHOST_OR_PACMAN_EATEN ], false, 0 );
					pGhost->setState( Ghost::DEAD );
				}
				else if( pGhost->getState( ) == Ghost::SEEKING_PACMAN )
				{
					Game::soundSystem->playSound( FMOD_CHANNEL_FREE, Game::soundEffects[ Game::SFX_GHOST_OR_PACMAN_EATEN ], false, 0 );
					Game::nPlayerLives--;
					Game::state = Game::GAME_OVER;
				}
				break;
			}
		}
	}
	
	return false;
}